/*----------------------------------------------------------------------------*/
/* Copyright 2019-2020,2022                                                   */
/*                                                                            */
/* NXP Confidential. This software is owned or controlled by NXP and may only */
/* be used strictly in accordance with the applicable license terms.          */
/* By expressly accepting such terms or by downloading, installing,           */
/* activating and/or otherwise using the software, you are agreeing that you  */
/* have read, and that you agree to comply with and are bound by, such        */
/* license terms. If you do not agree to be bound by the applicable license   */
/* terms, then you may not retain, install, activate or otherwise use the     */
/* software.                                                                  */
/*----------------------------------------------------------------------------*/

/** \file
* PRBS Application code.
*
* $Author$
* $Revision$
* $Date$
*/

#include <Nfcrdlib_PRBSApplication.h>
#include <phApp_Init.h>

#include "BoardSelection.h"
#include "phhalHw_Pn5190_Instr.h"
#include "phhalHw_Pn5190_Reg.h"
#include "phDriver.h"

/*******************************************************************************
**   Global Variable Declaration
*******************************************************************************/
#ifdef PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION
uint32_t aPRBSTaskBuffer[PRBS_TASK_STACK];
#else /* PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION */
#define aPRBSTaskBuffer       NULL
#endif /* PHOSAL_FREERTOS_STATIC_MEM_ALLOCATION */

/* Enable Below macro only when both abort and PRBS needed*/
//#define ENABLE_ENTER_TO_IDEL_STATE_OR_PRBS_VICE_VERSA

/*  */
#define EVTS_HEADER_BYTES       3
#define EVENT_LSB_INDEX         1
#define TLV_TYPE_FIELD_INDEX    1
#define TLV_LENGTH_MSB_INDEX    2
#define TLV_LENGTH_LSB_INDEX    3

/*******************************************************************************
**   Function Declarations
*******************************************************************************/
void NfcrdlibEx11_PRBSApplication(void *ptr);
static void phGeneratePRBSonRF(void);

/*******************************************************************************
**   Function Definitions
*******************************************************************************/

/*******************************************************************************
**   Main Function
*******************************************************************************/
int main (void)
{
    do
    {
        phStatus_t status = PH_ERR_INTERNAL_ERROR;
        phNfcLib_Status_t     dwStatus;

#ifdef PH_PLATFORM_HAS_ICFRONTEND
        phNfcLib_AppContext_t AppContext = {0};
#endif /* PH_PLATFORM_HAS_ICFRONTEND */

#ifndef PH_OSAL_NULLOS
        phOsal_ThreadObj_t PRBS;
#endif /* PH_OSAL_NULLOS */

        /* Perform Controller specific initialization. */
        phApp_CPU_Init();

        /* Perform OSAL Initialization. */
        (void)phOsal_Init();

        (void)phApp_Led_Init();

        DEBUG_PRINTF("\n *** PRBS Application started *** \n");

#ifdef PH_PLATFORM_HAS_ICFRONTEND
        status = phbalReg_Init(&sBalParams, sizeof(phbalReg_Type_t));
        CHECK_STATUS(status);

        AppContext.pBalDataparams = &sBalParams;
        dwStatus = phNfcLib_SetContext(&AppContext);
        CHECK_NFCLIB_STATUS(dwStatus);
#endif /* PH_PLATFORM_HAS_ICFRONTEND */

        /* Initialize library */
        dwStatus = phNfcLib_Init();
        CHECK_NFCLIB_STATUS(dwStatus);
        if(dwStatus != PH_NFCLIB_STATUS_SUCCESS) break;

        /* Set the generic pointer */
        pHal = phNfcLib_GetDataParams(PH_COMP_HAL);

        /* IRQ configuration for different HOST environments */
        status = phApp_Configure_IRQ();
        CHECK_STATUS(status);
        if(status != PH_ERR_SUCCESS) break;

#ifndef PH_OSAL_NULLOS

        PRBS.pTaskName = (uint8_t *) "PRBS";
        PRBS.pStackBuffer = aPRBSTaskBuffer;
        PRBS.priority = PRBS_TASK_PRIO;
        PRBS.stackSizeInNum = PRBS_TASK_STACK;
        phOsal_ThreadCreate(&PRBS.ThreadHandle, &PRBS, &NfcrdlibEx11_PRBSApplication, NULL);

        phOsal_StartScheduler();

        /* Print Error info */
        DEBUG_PRINTF("RTOS Error : Scheduler exited. \n");

#else
        (void)NfcrdlibEx11_PRBSApplication(NULL);
#endif /* PH_OSAL_NULLOS */
    } while(0);

    while(1); //Comes here if initialization failure or scheduler exit due to error

    return 0;
}


void NfcrdlibEx11_PRBSApplication(void *ptr)
{
#ifdef ENABLE_ENTER_TO_IDEL_STATE_OR_PRBS_VICE_VERSA
    phStatus_t Status;
    uint8_t bOption;
#endif /* ENABLE_ENTER_TO_IDEL_STATE_OR_PRBS_VICE_VERSA */

#ifndef PH_OSAL_LINUX
    (void)phApp_Led_On(PHDRIVER_PIN_BLED);
#endif

#ifdef ENABLE_ENTER_TO_IDEL_STATE_OR_PRBS_VICE_VERSA
    DEBUG_PRINTF(
               "\n Select the Option \n"
               "\t- Enter 1 to Generate PRBS on RF.\n"
               "\t- Enter 2 to Abort PRBS and Enter IDLE State.\n"
               "\n"
               );

    while(1)
    {
        DEBUG_PRINTF("Select Option:\n");
#ifdef __MCUXPRESSO
        DEBUG_PRINTF("(For MCUXpresso, you may have to press many enter keys after your input)");
#endif
        scanf("%d", &bOption);
        DEBUG_PRINTF("Option %d selected\n", bOption);

        switch (bOption)
        {
            case 1:
            {
#endif /* ENABLE_ENTER_TO_IDEL_STATE_OR_PRBS_VICE_VERSA */

                (void) phGeneratePRBSonRF();

#ifdef ENABLE_ENTER_TO_IDEL_STATE_OR_PRBS_VICE_VERSA
                break;
            }
            case 2:
            {
                Status = phhalHw_Pn5190_Instr_SwitchModeNormal(pHal);
                /* Switch to Normal Mode and Read Ideal Event*/
                if( PH_ERR_SUCCESS != (Status & PH_ERR_MASK ))
                {
#ifndef PH_OSAL_LINUX
                    (void)phApp_Led_Off(PHDRIVER_PIN_BLED);
                    (void)phApp_Led_Off(PHDRIVER_PIN_OLED);
                    (void)phApp_Led_On(PHDRIVER_PIN_RLED);
#endif
                    DEBUG_PRINTF("FAILED to IDLE State: Response is %d\n",Status);
                    while(1);
                }
                else
                {
#ifndef PH_OSAL_LINUX
                    (void)phApp_Led_Off(PHDRIVER_PIN_BLED);
                    (void)phApp_Led_Off(PHDRIVER_PIN_GLED);
                    (void)phApp_Led_On(PHDRIVER_PIN_OLED);
#endif
                    DEBUG_PRINTF("SUCCESS: Entered IDLE State \n");
                }
                break;
            }

            default:
                DEBUG_PRINTF("Invalid selection!!!. \n");
        }
    }
#else
    while(1);
#endif /* ENABLE_ENTER_TO_IDEL_STATE_OR_PRBS_VICE_VERSA */
}

static void phGeneratePRBSonRF(void)
{
    phStatus_t wStatus;
    uint32_t bPrbs_type = 0;
    uint32_t bTech_type = 1;

#ifdef DEBUG
    bPrbs_type = 2;
    bTech_type = 0;

    do
    {
        DEBUG_PRINTF(
           "\n Select below PRBS Options \n"
           "\t- Enter 0 to Generate PRBS9.\n"
           "\t- Enter 1 to Generate PRBS15.\n"
           " Entered value = "
           );
        DEBUG_SCANF("%d", &bPrbs_type);
        DEBUG_PRINTF("\n");
    }while((bPrbs_type != 0U) && (bPrbs_type != 1U));

    do
    {
        DEBUG_PRINTF(
           "\n Select any of the below Technology Options \n"
           "\t- Enter 1 : Type A Tx at 106Kbps.\n"
           "\t- Enter 2 : Type B Tx at 106Kbps.\n"
           "\t- Enter 3 : Type F Tx at 212Kbps.\n"
           "\t- Enter 4 : ISO15693 Tx at 1 out of 4.\n"
           "\t- Enter 5 : RFU.\n"
           "\t- Enter 6 : ISO18000p3m3 Tx at 9.44Kbps.\n"
           "\t- Enter 7 : Type F Tx at 424Kbps.\n"
           " Entered value = "
           );
        DEBUG_SCANF("%d", &bTech_type);
        DEBUG_PRINTF("\n");
    }while(bTech_type == 0U);

    if (bTech_type == 7U)
    {
        bTech_type = PHHAL_HW_CARDTYPE_FELICA_424;
    }
#endif /* DEBUG */

    /* Field OFF */
    wStatus = phhalHw_FieldOff(pHal);
    CHECK_STATUS(wStatus);

    wStatus = phhalHw_Wait(pHal, PHHAL_HW_TIME_MICROSECONDS, 5100);
    CHECK_STATUS(wStatus);

    wStatus = phhalHw_ApplyProtocolSettings(pHal, bTech_type);
    CHECK_STATUS(wStatus);

    /* Disable RFCA (if supported) */
    wStatus = phhalHw_SetConfig(pHal, PHHAL_HW_CONFIG_RFCA, PH_OFF);
    CHECK_STATUS(wStatus);

    /* Perform Field ON after Apply protocol settings without performing I-RFCA. */
    wStatus = phhalHw_FieldOn(pHal);
    CHECK_STATUS(wStatus);

    wStatus = phhalHw_Pn5190_Instr_PrbsTest(pHal, bPrbs_type);
    if(wStatus != PH_ERR_SUCCESS)
    {
#ifndef PH_OSAL_LINUX
        (void)phApp_Led_Off(PHDRIVER_PIN_BLED);
        (void)phApp_Led_Off(PHDRIVER_PIN_OLED);
        (void)phApp_Led_On(PHDRIVER_PIN_RLED);
#endif
        DEBUG_PRINTF("FAILED to Start PRBS on RF: Response is %d\n",wStatus);
        while(1);
    }
    else
    {
#ifndef PH_OSAL_LINUX
        (void)phApp_Led_Off(PHDRIVER_PIN_BLED);
        (void)phApp_Led_Off(PHDRIVER_PIN_OLED);
        (void)phApp_Led_On(PHDRIVER_PIN_GLED);
#endif
        DEBUG_PRINTF("SUCCESS: PRBS Generation on RF is started \n");
    }
}

#ifdef NXPBUILD__PHHAL_HW_TARGET
/* Stubbed definitions in case TARGET is enabled */
uint8_t  sens_res[2]     = {0x04, 0x00};
uint8_t  nfc_id1[3]      = {0xA1, 0xA2, 0xA3};
uint8_t  sel_res         = 0x40;
uint8_t  nfc_id3         = 0xFA;
uint8_t  poll_res[18]    = {0x01, 0xFE, 0xB2, 0xB3, 0xB4, 0xB5,
                                   0xB6, 0xB7, 0xC0, 0xC1, 0xC2, 0xC3,
                                   0xC4, 0xC5, 0xC6, 0xC7, 0x23, 0x45 };
#endif /* NXPBUILD__PHHAL_HW_TARGET */

/***********************************************************************************************
 *                            End Of File
 **********************************************************************************************/
